package com.test.realcityalfa.frmwrk;

import java.io.File;
import java.io.FileOutputStream;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Stack;
import com.test.realcityalfa.Constants;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;

public abstract class DrawableManager {
	private Context context;
	private HashMap<String, Bitmap> imageMap = new HashMap<String, Bitmap>();
	private File cacheDir;	
	private ImageQueue imageQueue = new ImageQueue();
	private Thread imageLoaderThread = new Thread(new ImageQueueManager());
	
	public abstract void handleConnectionTimeout(SocketTimeoutException ex);
	public abstract void handleLoadingFinished(Object object);
	
	public DrawableManager(Context context)
	{
		this.context = context;
		initCacheDir();
	}

	
	private void initCacheDir()
	{
		
		if(android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
		{
			File sdDir = android.os.Environment.getExternalStorageDirectory();
			cacheDir = new File(sdDir, "data/realcity/");
			//cacheDir.mkdir();//test
		}
		else
		{
			cacheDir = context.getCacheDir();
		}
		cacheDir = context.getCacheDir();
		Log.d("DrawableManager", "Cache directory: " + cacheDir);
		if(!cacheDir.exists())
		{
			cacheDir.mkdir();
		}
	}
	
	public void displayCommercial(String url, Activity activity, ImageView view, ProgressBar prgBar)
	{
		if(prgBar != null){prgBar.setVisibility(View.VISIBLE);}
		if(imageMap.containsKey(url))
		{
			if(prgBar != null){prgBar.setVisibility(View.GONE);}
			//view.setImageBitmap(imageMap.get(url));
		} 
		else
		{
			
			queueImage(url, activity, view, prgBar);
			//view.setImageResource(com.test.realcityalfa.R.drawable.placeholder);
		}
	}
	
	
	public void displayImage(String url, Activity activity, ImageView view, ProgressBar prgBar)
	{
		if(prgBar != null){prgBar.setVisibility(View.VISIBLE);}
		if(imageMap.containsKey(url))
		{
			Log.d("DrawableManager", "Image exists. Using cache.");
			if(prgBar != null){prgBar.setVisibility(View.GONE);}
			view.setImageBitmap(imageMap.get(url));
		}
		else
		{
			Log.d("DrawableManager", "Image NOT exists. Loading.");
			queueImage(url, activity, view, prgBar);
			view.setImageResource(com.test.realcityalfa.R.drawable.placeholder);
		}
		
	}
	
	private void queueImage(String url,Activity activity, ImageView view, ProgressBar prgBar)
	{
		imageQueue.clean(view);
		ImageReference ref = new ImageReference(url, view, prgBar);
		
		synchronized (imageQueue.imageRefs) 
		{
			imageQueue.imageRefs.push(ref);
			imageQueue.imageRefs.notifyAll();			
		}
		
		if(imageLoaderThread.getState() == Thread.State.NEW)
		{imageLoaderThread.start();}		
	}
	
	private Bitmap getBitmap(String url)
	{
		
		//test image url http://media.realcity.cz/get_image.php?id=9604252&key=ad
		String filename = String.valueOf(url.hashCode());
		File f = new File(cacheDir, filename);
		
		//if image exists in cache
		Bitmap bmp = BitmapFactory.decodeFile(f.getPath());
		if(bmp != null){return bmp;}		
		
		try
		{
			//set ups the connection
			URLConnection urlConnection = new URL(url).openConnection();
			urlConnection.setConnectTimeout(Constants.InternetConnection.CONNECTION_TIMEOUT);
			urlConnection.setReadTimeout(Constants.InternetConnection.CONNECTION_READ_TIMEOUT);
			
			bmp = BitmapFactory.decodeStream(urlConnection.getInputStream());
			writeFile(bmp, f);
			
			
			return bmp;
		}
		catch(SocketTimeoutException e)
		{
			handleConnectionTimeout(e);
			return null;
		}
		catch(Exception e)
		{
			e.printStackTrace();
			return null;
		}				
	}
	
	private void writeFile(Bitmap bmp, File f)
	{
		FileOutputStream out = null;
		
		try
		{
			out = new FileOutputStream(f);
			bmp.compress(Bitmap.CompressFormat.JPEG, 80, out);
		}
		catch(Exception e)
		{e.printStackTrace();}
		finally
		{
			try
			{
				if(out != null){out.close();}
			}
			catch(Exception e)
			{e.printStackTrace();}
		}
		
		
	}
	
	/////classes//////
	private class ImageReference
	{
		public String url;
		public ImageView imageView;
		public ProgressBar prgBar;
		
		public ImageReference(String url, ImageView img, ProgressBar prgBar)
		{
			this.url = url;
			this.imageView = img;
			this.prgBar = prgBar;
		}
	}
	
	private class ImageQueue
	{
		private Stack<ImageReference> imageRefs = new Stack<ImageReference>();
		
		public void clean(ImageView view)		
		{
			for(int i = 0; i < imageRefs.size();i++)
			{
				if(imageRefs.get(i).imageView == view)
				{
					imageRefs.remove(i);					
				}
			}			
		}		
	}
	
	private class ImageQueueManager implements Runnable
	{

		@Override
		public void run() 
		{
			try
			{
				while(true)
				{
					//thread waits until there is any image to process in queue
					if(imageQueue.imageRefs.size() == 0)
					{
						synchronized (imageQueue.imageRefs) 
						{
							imageQueue.imageRefs.wait();
							//imageLoaderThread.wait();
						}						
					}
					
					if(imageQueue.imageRefs.size() != 0)
					{
						ImageReference imageToLoad;
						
						synchronized (imageQueue.imageRefs) 
						{
							imageToLoad = imageQueue.imageRefs.pop();
						}
										
						Bitmap bmp = getBitmap(imageToLoad.url);
						//Looper.prepare();
						//handleLoadingFinished("done");
						imageMap.put(imageToLoad.url,bmp);
						
						Object tag = imageToLoad.imageView.getTag();
						
						if(tag != null && ((String)tag).equals(imageToLoad.url))
						{
							BitmapDisplayer bmpDisplayer = new BitmapDisplayer(bmp, imageToLoad.imageView, imageToLoad.prgBar);
							
							Context c = imageToLoad.imageView.getContext();
							Log.d("TEST", c.getCacheDir().toString());
							Activity a = (Activity) c;
							a.runOnUiThread(bmpDisplayer);
						}
					}
					
					if(imageLoaderThread.interrupted())
					{break;}
				}
			}
			catch(InterruptedException e){e.printStackTrace();}
			
		}
	}
	
	private class BitmapDisplayer implements Runnable
	{
		Bitmap bmp;
		ImageView view;
		ProgressBar prgBar;
		
		public BitmapDisplayer(Bitmap bmp, ImageView view, ProgressBar prg_bar)
		{
			this.bmp = bmp;
			this.view = view;
			this.prgBar = prg_bar;
		}

		@Override
		public void run() 
		{
			if(prgBar != null){prgBar.setVisibility(View.GONE);}
			if(bmp != null)
			{
				view.setImageBitmap(bmp);
				//Looper.prepare();
				//handleLoadingFinished("done");
			}
			else{view.setImageResource(com.test.realcityalfa.R.drawable.placeholder);}
		}
		
	}
	

	
}
